"""Copyright 2011 Thomas Anesta, Jonathan Brenner, Tyler Moylat, Rosa Tung, Sean Kim"""

"""

This file is part of Bubbles

Bubbles is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Bubbles is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with Foobar.  If not, see <http://www.gnu.org/licenses/>.

"""




import pygame
import BubblesConstants
import math
import random
import BubblesShot

BEE_WIDTH = 63
BEE_HEIGHT = 69
BEE_FRAMES_LIST = [int(0), 1, 2, 1]
#BEE_FRAMES = 4
BEE_FRAMES_DELAY = 2#change every two frames
BEE_HIT_DURATION = 4 #not necessary bee has no hit animation
BEE_DEATH_FRAMES = 0 #no death for bee too healthy
DRAGONFLY_WIDTH = 157
DRAGONFLY_HEIGHT = 77#85, was until now
DRAGONFLY_FRAMES_LIST = [int(0), 1, 2, 1]
#DRAGONFLY_FRAMES = 4
DRAGONFLY_FRAMES_DELAY = 2#change every two frames
DRAGONFLY_HIT_DURATION = 15
DRAGONFLY_DEATH_FRAMES = 5
DRAGONFLY_DEATH_WIDTH = 60
DRAGONFLY_DEATH_HEIGHT = 60
MOSQUITO_WIDTH = 51#52
MOSQUITO_HEIGHT = 51#52
MOSQUITO_FRAMES_LIST = [int(0), 1, 2, 1]
#MOSQUITO_FRAMES = 4
MOSQUITO_FRAMES_DELAY = 2#change every two frames
MOSQUITO_HIT_DURATION = 15
MOSQUITO_DEATH_FRAMES = 5
MOSQUITO_DEATH_WIDTH = 60
MOSQUITO_DEATH_HEIGHT = 60

SATELLITE_WIDTH = 640
SATELLITE_HEIGHT = 396

SATTELITE_DEATH_FRAMES = 30


POWERUP_CHANCE = 0.3
POWERUP_DISTRIBUTION = 0.5


NORMAL_CANNON = 0
MAIN_CANNON = 1
HOMING_CANNON = 2
ANGLE_CANNON = 3

DEFAULT_ANGLE = 0
ANGLE_ONE = 1
ANGLE_TWO = 2 
ANGLE_THREE = 3
ANGLE_FOUR = 4

PANEL_WIDTH = 38
PANEL_HEIGHT_A = 39
PANEL_HEIGHT_B = 44
PANEL_HEIGHT_C = 51
PANEL_HEIGHT_D = 56

class Enemy(object):
    def __init__(self, xpos, ypos):
        self.xpos = xpos
        self.ypos = ypos
        self.xvel = 0
        self.yvel = 0
        
        self.health = 1
        self.status = BubblesConstants.STATUS_ACTIVE
        self.frames = 0
        self.frames_list = [0]
        self.f_delay = 1
        self.is_hit = False
        self.hit_frame = int(0)
        self.hit_dif = int(0)
        self.death_frames = int(0)
        self.points_worth = 0
        
        self.enemy_explode = pygame.mixer.Sound("sfx/enemy_explode.wav")
        self.enemy_hit = pygame.mixer.Sound("sfx/enemy_hit.wav")
        
    def update(self):
        self.xpos += self.xvel
        self.ypos += self.yvel
        
    def draw(self):
        return
        
    def get_powerup(self):#does not require reference to self
        p_val = random.random()
        if p_val >= POWERUP_CHANCE:
            return BubblesConstants.POWERUP_NONE
        else:
            p_sign = random.random()
            if p_sign >= POWERUP_DISTRIBUTION:
                return BubblesConstants.POWERUP_POSITIVE
            else:
                return BubblesConstants.POWERUP_NEGATIVE



    def kill(self, score):
        self.status = BubblesConstants.STATUS_DEAD
        score[0] += self.points_worth
    
    def leave(self):
        self.status = BubblesConstants.STATUS_OFFSCREEN
        
    def advance_frame(self):
        self.frames += 1

class Bee(Enemy):
    """Moves Down"""
    def __init__(self, xpos, ypos):
        Enemy.__init__(self, xpos, ypos)
        self.type = BubblesConstants.BEE_TYPE
        self.image = pygame.image.load("gfx/Bubble_Bee.png").convert_alpha()
        self.rect = self.image.get_rect()
        self.rect.width = BEE_WIDTH
        self.rect.height = BEE_HEIGHT
        self.rect.x = self.xpos - self.rect.width/2
        self.rect.y = self.ypos - self.rect.height/2
        self.xvel = 0
        self.yvel = 15
        self.radius = BEE_WIDTH/2
        self.health = 1000
        self.status = BubblesConstants.STATUS_ACTIVE
        self.frames = 0
        self.frames_list = BEE_FRAMES_LIST
        self.f_delay = BEE_FRAMES_DELAY
        self.is_hit = False
        self.hit_frame = int(0)
        self.hit_dif = BEE_HIT_DURATION
        self.death_frames = BEE_DEATH_FRAMES * BEE_FRAMES_DELAY
        self.points_worth = 0
        
        self.enemy_hit = pygame.mixer.Sound("sfx/bee_hit.ogg")
        
    def update(self, shots, player, score):
        future = self.rect.move(self.xvel, self.yvel)
        self.rect = future

        Enemy.update(self)
        
        #collision with shots
        for shot in shots:
            distance_to_shot = math.sqrt(math.pow(shot.xpos - self.xpos, 2) + math.pow(shot.ypos - self.ypos, 2))
            if (self.radius + shot.radius) >= distance_to_shot:
                self.health -= 1
                self.is_hit = True
                self.hit_frame = self.frames
                shot.active = False
                if self.health <= 0:
                    self.kill(score)
                    self.enemy_explode.play()
                    self.image = pygame.image.load("gfx/Bubble_Bee.png").convert_alpha()
                    return BubblesConstants.DEAD_RETURN#enemy is dead need no more work done
                self.enemy_hit.play()
        
        
                
        #collision with player
        distance_to_player = math.sqrt(math.pow(player.xpos - self.xpos, 2) + math.pow(player.ypos - self.ypos, 2))
        if (self.radius + player.radius) >= distance_to_player:
            self.hit_frame = self.frames
            self.image = pygame.image.load("gfx/Bubble_Bee.png").convert_alpha()
            self.kill(score)#dies on collision
            return BubblesConstants.COLLISION_PLAYER_RETURN
        
        if self.rect.top > BubblesConstants.WINDOW_HEIGHT - BubblesConstants.WINDOW_HUD:
            self.leave()
            return BubblesConstants.OFF_SCREEN_RETURN
            
        
        return BubblesConstants.NO_COLLISION_RETURN
    
    def draw(self, screen):#there is no difference for bees between hit and not hit
        if self.is_hit == True:
            if (self.frames - self.hit_frame) < self.hit_dif:
                screen.blit(self.image, self.rect, pygame.Rect(0, BEE_HEIGHT * self.frames_list[((self.frames/self.f_delay) % len(self.frames_list))], BEE_WIDTH, BEE_HEIGHT))
                self.advance_frame()
                return
            else:
                self.is_hit = False
        else: 
            pass
        
        screen.blit(self.image, self.rect, pygame.Rect(0, BEE_HEIGHT * self.frames_list[((self.frames/self.f_delay) % len(self.frames_list))], BEE_WIDTH, BEE_HEIGHT))
        self.advance_frame()
        
    def draw_death(self, screen):
        pass
                
class Dragonfly(Enemy):
    """Zig Zag"""
    def __init__ (self, xpos, ypos ):
        Enemy.__init__(self, xpos, ypos)
        self.type = BubblesConstants.DRAGONFLY_TYPE
        self.image = pygame.image.load("gfx/Bubble_Dragonfly.png").convert_alpha()
        self.rect = self.image.get_rect()
        self.rect.x = self.xpos - self.rect.width/2
        self.rect.y = self.ypos - self.rect.height/2
        self.xvel = 5
        self.yvel = 8
        self.rect.width = DRAGONFLY_WIDTH
        self.rect.height = DRAGONFLY_HEIGHT
        self.health = 10
        self.status = BubblesConstants.STATUS_ACTIVE
        
        
        self.frames = 0
        self.frames_list = DRAGONFLY_FRAMES_LIST
        self.f_delay = DRAGONFLY_FRAMES_DELAY
        self.is_hit = False
        self.hit_frame = int(0)
        self.hit_dif = DRAGONFLY_HIT_DURATION
        self.death_frames = DRAGONFLY_DEATH_FRAMES * DRAGONFLY_FRAMES_DELAY
        self.points_worth = 400
    
    def update(self, shots, player, score):
        future = self.rect.move(self.xvel, self.yvel)
        if future.left < 0:
            future.left = 0
            self.xvel = -self.xvel
        elif future.right > BubblesConstants.WINDOW_WIDTH:
            future.right = BubblesConstants.WINDOW_WIDTH
            self.xvel = -self.xvel

        self.rect = future
        for shot in shots:
            if self.collision(shot):
                self.health -= 1
                shot.active = False
                self.is_hit = True
                self.hit_frame = self.frames
                if self.health <= 0:
                    self.kill(score)
                    self.enemy_explode.play()
                    self.image = pygame.image.load("gfx/Bubble_Dragonfly_Death.png").convert_alpha()
                    return BubblesConstants.DEAD_RETURN#enemy is dead need no more work done
                self.enemy_hit.play()
        
        if self.collision(player):
            self.hit_frame = self.frames
            self.image = pygame.image.load("gfx/Bubble_Dragonfly_Death.png").convert_alpha()
            self.kill(score)#dies on collision
            return BubblesConstants.COLLISION_PLAYER_RETURN
        
        if self.rect.top > BubblesConstants.WINDOW_HEIGHT - BubblesConstants.WINDOW_HUD:
            self.leave()
            return BubblesConstants.OFF_SCREEN_RETURN
        
        return BubblesConstants.NO_COLLISION_RETURN

    def collision(self,shot):
        if (shot.rect.left > self.rect.left and shot.rect.right < self.rect.right) or (shot.rect.top > self.rect.top and shot.rect.bottom < self.rect.bottom):
            if shot.rect.colliderect(self.rect):
                return True
        else:
            # bottom left corner
            x = 0
            y = 0
            if shot.rect.left < self.rect.left and shot.rect.bottom > self.rect.bottom:
                x = self.rect.bottomleft[0]
                y = self.rect.bottomleft[1]
            # top left corner
            elif shot.rect.left < self.rect.left and shot.rect.top < self.rect.top:
                x = self.rect.topleft[0]
                y = self.rect.topleft[1]             
            # bottom right corner   
            elif shot.rect.right > self.rect.right and shot.rect.bottom > self.rect.bottom:
                x = self.rect.bottomright[0]
                y = self.rect.bottomright[1]
            # top right corner
            elif shot.rect.right > self.rect.right and shot.rect.top < self.rect.top:
                x = self.rect.topright[0]
                y = self.rect.topright[1]     
            else:
                return False
            distance = math.sqrt(math.pow(shot.xpos - x, 2) + math.pow(shot.ypos - y, 2))
            if distance < shot.radius:
                return True
        return False
            
    def draw(self, screen):
        if self.is_hit == True:
            if (self.frames - self.hit_frame) < self.hit_dif:
                screen.blit(self.image, self.rect, pygame.Rect(DRAGONFLY_WIDTH * self.frames_list[((self.frames/self.f_delay) % len(self.frames_list))], (self.frames % 2)*DRAGONFLY_HEIGHT, DRAGONFLY_WIDTH, DRAGONFLY_HEIGHT))
                self.advance_frame()
                return
            else:
                self.is_hit = False
        else: 
            pass
        
        screen.blit(self.image, self.rect, pygame.Rect(DRAGONFLY_WIDTH * self.frames_list[((self.frames/self.f_delay) % len(self.frames_list))], 0, DRAGONFLY_WIDTH, DRAGONFLY_HEIGHT))
        self.advance_frame()

    def draw_death(self, screen):
        screen.blit(self.image, self.rect, pygame.Rect(DRAGONFLY_DEATH_WIDTH * ( (self.frames - self.hit_frame)/self.f_delay), 0, DRAGONFLY_DEATH_WIDTH, DRAGONFLY_DEATH_HEIGHT))
        self.advance_frame()
        
class Mosquito(Enemy):
    """Homing"""
    def __init__(self, xpos, ypos):
        Enemy.__init__(self, xpos, ypos)
        self.type = BubblesConstants.MOSQUITO_TYPE
        self.image = pygame.image.load("gfx/Bubble_Mosquito.png").convert_alpha()
        self.rect = self.image.get_rect()
        self.rect.width = MOSQUITO_WIDTH
        self.rect.height = MOSQUITO_HEIGHT
        self.rect.x = self.xpos - self.rect.width/2
        self.rect.y = self.ypos - self.rect.height/2
        self.xvel = 3
        self.yvel = 4
        self.radius = MOSQUITO_WIDTH/2
        self.health = 3
        self.status = BubblesConstants.STATUS_ACTIVE
        
        
        self.frames = 0
        self.frames_list = MOSQUITO_FRAMES_LIST
        self.f_delay = MOSQUITO_FRAMES_DELAY
        self.is_hit = False
        self.hit_frame = int(0)
        self.hit_dif = MOSQUITO_HIT_DURATION
        self.death_frames = MOSQUITO_DEATH_FRAMES * MOSQUITO_FRAMES_DELAY
        self.points_worth = 100

    def update(self, shots, player, score):
        """updates the mosquito's position"""
        # if the player is to the left of the mosquito
        if player.xpos < self.rect.x:
            tmpXVel = -self.xvel
        # if the player is to the right of the mosquito
        elif player.xpos > self.rect.x + self.rect.w:
            tmpXVel = self.xvel
        else:
            tmpXVel = 0
        # if the player is above the mosquito
        if player.ypos < self.rect.y: 
            tmpYVel = -self.yvel
        # if the player is below the mosquito        
        elif player.ypos > self.rect.y + self.rect.h:
            tmpYVel = self.yvel
        else:
            tmpYVel = 0

        future = self.rect.move(tmpXVel,tmpYVel)
        self.rect = future
        self.xpos = self.rect.x + self.rect.width/2
        self.ypos = self.rect.y + self.rect.height/2
        #Enemy.update(self)
        
        #collision with shots
        for shot in shots:
            distance_to_shot = math.sqrt(math.pow(shot.xpos - self.xpos, 2) + math.pow(shot.ypos - self.ypos, 2))
            if (self.radius + shot.radius) >= distance_to_shot:
                shot.active = False
                self.is_hit = True
                self.hit_frame = self.frames
                self.health -= 1
        # set the enemy to dead if it's health is at or below 0
                if self.health <= 0:
                    self.kill(score)
                    self.enemy_explode.play()
                    self.image = pygame.image.load("gfx/Bubble_Mosquito_Death.png").convert_alpha()
                    return BubblesConstants.DEAD_RETURN
                self.enemy_hit.play()
            
        #collision with player
        distance_to_player = math.sqrt(math.pow(player.xpos - self.xpos, 2) + math.pow(player.ypos - self.ypos, 2))
        if (self.radius + player.radius) >= distance_to_player:
            self.hit_frame = self.frames
            self.image = pygame.image.load("gfx/Bubble_Mosquito_Death.png").convert_alpha()
            self.kill(score)#dies on collision
            return BubblesConstants.COLLISION_PLAYER_RETURN
        
        return BubblesConstants.NO_COLLISION_RETURN
    
    def draw(self, screen):
        if self.is_hit == True:
            if (self.frames - self.hit_frame) < self.hit_dif:
                screen.blit(self.image, self.rect, pygame.Rect(MOSQUITO_WIDTH * self.frames_list[((self.frames/self.f_delay) % len(self.frames_list))], (self.frames % 2)*MOSQUITO_HEIGHT, MOSQUITO_WIDTH, MOSQUITO_HEIGHT))
                self.advance_frame()
                return
            else:
                self.is_hit = False
        else: 
            pass
        
        screen.blit(self.image, self.rect, pygame.Rect(MOSQUITO_WIDTH * self.frames_list[((self.frames/self.f_delay) % len(self.frames_list))], 0, MOSQUITO_WIDTH, MOSQUITO_HEIGHT))
        self.advance_frame()

    def draw_death(self, screen):
        screen.blit(self.image, self.rect, pygame.Rect(DRAGONFLY_DEATH_WIDTH * ( (self.frames - self.hit_frame)/self.f_delay), 0, DRAGONFLY_DEATH_WIDTH, DRAGONFLY_DEATH_HEIGHT))
        self.advance_frame()
    
class Satellite(Enemy):
    def __init__(self, xpos, ypos):
        Enemy.__init__(self, xpos, ypos)
        self.type = BubblesConstants.SATELLITE_TYPE
        self.health = 32
        self.image = pygame.image.load("gfx/Bubble_Satellite.png").convert_alpha()
        self.rect = self.image.get_rect()
        self.rect.width = SATELLITE_WIDTH
        self.rect.height = SATELLITE_HEIGHT
        self.rect.x = self.xpos
        self.rect.y = self.ypos
        self.status = BubblesConstants.STATUS_ACTIVE
        
        self.death_image = pygame.image.load("gfx/Bubble_Satellite_Death.png").convert_alpha()
        
        self.hit_frame = 0
        self.death_frames = 60
            
        self.panels = []
        self.shots = []

        self.shot_delay = 45
        self.shot_cooldown = 0

        self.shot_xvel = 0
        self.shot_yvel = 4

        self.homing_shot_xvel = 2
    
        self.forward = True

        self.active_cannons = [[Cannon(False, 278,ypos + 336, HOMING_CANNON, "" ), Cannon(False, 318,ypos + 330, HOMING_CANNON, ""), Cannon(False, 356,ypos + 336, HOMING_CANNON, "") ],
                               [Cannon(True, 255,ypos + 356, ANGLE_CANNON, "left"), Cannon(True, 315,ypos + 358, MAIN_CANNON, ""),Cannon(True, 375,ypos + 356, ANGLE_CANNON, "right") ],
                               [Cannon(True, 278,ypos + 386, NORMAL_CANNON, ""), Cannon(True, 318,ypos + 390, HOMING_CANNON, ""),Cannon(True, 356,ypos + 386, NORMAL_CANNON, "") ]]

        self.active_upgrades = [False,False,False,False]
        
        self.panel_die_sound = pygame.mixer.Sound("sfx/panel_explode.wav")

        self.frame = 0
        self.frame_frequency = 45
        
        self.yvel = 1

        self.f_delay = 30
        self.death_frame = 0

        yoffset = 183
        for i in range(4):            
            xoffset = 3
            if i == 0:
                pass
            elif i == 1:
                yoffset = yoffset + PANEL_HEIGHT_A + 2
            elif i == 2:
                yoffset = yoffset + PANEL_HEIGHT_B + 1
            elif i == 3:
                yoffset = yoffset + PANEL_HEIGHT_C + 1
            for j in range(8):
                self.panels.append(Panel(self.rect.x + xoffset, self.rect.y + yoffset, i))
                xoffset = xoffset + PANEL_WIDTH + 1
                if j == 3:
                    xoffset = 482
                if j == 7:
                    xoffset = 2

    def update(self, shots, player, score):
        self.advance_frame()
            
        self.rect.move_ip(0,self.yvel)   
        for panel in self.panels:
            panel.move(self.yvel)
        for row in self.active_cannons:
            for cannon in row: 
                cannon.move(self.yvel)
        if self.rect.top == 0:
            self.yvel = 0 
    
        for i,panel in enumerate(self.panels):
            if self.rect.top == 0:
                if panel.update(shots,player) == BubblesConstants.DEAD_RETURN:
                    print "PANEL DIED" 
                    self.health -= 1
                    print self.health
                    self.panel_die_sound.play()

        if self.health <= 0 :
            print "DURRRR"
            self.hit_frame = self.frames
            self.image = self.death_image
            self.rect = self.image.get_rect()
            self.rect.x = self.xpos
            self.rect.y = self.ypos
            self.kill([0])

        if self.shot_cooldown <= 0 and self.rect.top == 0:
            self.shoot(player)
            self.shot_cooldown = self.shot_delay
        self.shot_cooldown -= 1

        for shot in self.shots:
            shot.update()        

            

        #shot collision with player
        for i,shot in enumerate(self.shots):
            if shot.rect.bottom > BubblesConstants.WINDOW_HEIGHT or shot.active == False:
                del self.shots[i]

            distance_to_player = math.sqrt(math.pow(player.xpos - shot.xpos, 2) + math.pow(player.ypos - shot.ypos, 2))
            if (shot.radius + player.radius) >= distance_to_player:
                del self.shots[i]
                return BubblesConstants.COLLISION_PLAYER_RETURN   

    def draw(self, screen):
        if self.death_frame < 40:
            if self.frames == self.frame_frequency:
                if self.forward == True:
                    self.frame = self.frame + 1
                    if self.frame == 4:
                        self.forward = False
                else:
                    self.frame = self.frame - 1
                    if self.frame == 0:
                        self.forward = True
                self.frames = 0 
                    
            screen.blit( self.image, self.rect, (0,0 + self.frame * SATELLITE_HEIGHT,SATELLITE_WIDTH,SATELLITE_HEIGHT))
            for panel in self.panels:
                panel.draw(screen)
            for shot in self.shots:
                shot.draw(screen)

    def draw_death(self,screen):
        if self.death_frame < 40:
            screen.blit(self.image, self.rect, pygame.Rect(0, self.rect.height * ((self.death_frame / 20 )% 2), self.rect.width, self.rect.height))
            self.death_frame = self.death_frame + 1
            self.advance_frame()
    
    def shoot( self,player ):
        if self.health < 8 and self.active_upgrades[3] == False:
            self.active_upgrades[3] = True

        elif self.health < 16 and self.active_upgrades[2] == False:  
            for row in self.active_cannons:
                for cannon in row:
                    if cannon.cannon_type == HOMING_CANNON:
                        cannon.active = True
            self.active_upgrades[2] = True

        elif self.health < 24 and self.active_upgrades[1] == False:
            self.shot_delay = self.shot_delay - 2
            self.active_upgrades[1] = True

        elif self.health < 30 and self.active_upgrades[0] == False:
            for row in self.active_cannons:
                for cannon in row:
                    if cannon.cannon_type == ANGLE_CANNON:
                        cannon.active = True
            self.active_upgrades[0] = True

        for row in self.active_cannons:
            for cannon in row:
                if cannon.active == True:
                    if cannon.cannon_type == MAIN_CANNON:
                        self.shots.append(BubblesShot.Shot(cannon.xpos, cannon.ypos, self.shot_xvel, self.shot_yvel, 1, player))
                    elif cannon.cannon_type == NORMAL_CANNON:
                        self.shots.append(BubblesShot.Shot(cannon.xpos, cannon.ypos, self.shot_xvel, self.shot_yvel, 1, player))
                    elif cannon.cannon_type == HOMING_CANNON:
                        self.shots.append(BubblesShot.Homing_Shot(cannon.xpos, cannon.ypos, self.homing_shot_xvel, 2, 1, player))
                    elif cannon.cannon_type == ANGLE_CANNON:
                        self.shots.append(BubblesShot.Shot(cannon.xpos, cannon.ypos, self.shot_xvel + cannon.angle[0], self.shot_yvel + cannon.angle[1], 1, player))
                        cannon.change_angle()

class Cannon(object):
    def __init__( self, active, xpos, ypos , cannon_type, pos ):
        self.active = active
        self.xpos = xpos
        self.ypos = ypos
        self.cannon_type = cannon_type

        self.angle_type = DEFAULT_ANGLE
        self.angle = ( 0 , 0 )    
        self.forwards = True
        self.pos = pos
    
    def change_angle( self ):
        if self.angle_type == DEFAULT_ANGLE:
            self.angle_type = ANGLE_ONE
            self.forwards = True
            if self.pos == "left":
                self.angle = ( -2.8, 0 )
                self.xpos = 244
                self.ypos = 356
            elif self.pos == "right":
                self.angle = ( 2.8, 0 )
                self.xpos = 390
                self.ypos = 356
        elif self.angle_type == ANGLE_ONE:
            if self.forwards == True:        
                self.angle_type = ANGLE_TWO
                if self.pos == "left":
                    self.angle = ( -3.5, 0 )
                    self.xpos = 236
                    self.ypos = 354
                elif self.pos == "right":
                    self.angle = ( 3.5, 0 )
                    self.xpos = 400
                    self.ypos = 354
            else:
                self.angle_type = DEFAULT_ANGLE
                if self.pos == "left":
                    self.angle = ( 0, 0 )
                    self.xpos = 256
                    self.ypos = 360
                elif self.pos == "right":
                    self.angle = ( 0, 0 )
                    self.xpos = 376
                    self.ypos = 360

        elif self.angle_type == ANGLE_TWO:
            if self.forwards == True:
                self.angle_type = ANGLE_THREE
                if self.pos == "left":
                    self.angle = ( -4.4, 0 )
                    self.xpos = 228
                    self.ypos = 352
                elif self.pos == "right":
                    self.angle = ( 4.4, 0 )
                    self.xpos = 406
                    self.ypos = 352
            else:
                self.angle_type = ANGLE_ONE
                if self.pos == "left":
                    self.angle = ( -2.8, 0 )
                    self.xpos = 244
                    self.ypos = 356
                elif self.pos == "right":
                    self.angle = ( 2.8, 0 )
                    self.xpos = 390
                    self.ypos = 356
        elif self.angle_type == ANGLE_THREE:
            if self.forwards == True:
                self.angle_type = ANGLE_FOUR
                if self.pos == "left":
                    self.angle = ( -6.2, -1.5 )
                    self.xpos = 220
                    self.ypos = 344
                elif self.pos == "right":
                    self.angle = ( 6.2, -1.5 )
                    self.xpos = 412
                    self.ypos = 344
            else:
                self.angle_type = ANGLE_TWO
                if self.pos == "left":
                    self.angle = ( -3.5, 0 )
                    self.xpos = 236
                    self.ypos = 354
                elif self.pos == "right":
                    self.angle = ( 3.5, 0 )
                    self.xpos = 400
                    self.ypos = 354

        elif self.angle_type == ANGLE_FOUR:
            self.angle_type = ANGLE_THREE
            self.forwards = False
            self.angle_type = ANGLE_THREE
            if self.pos == "left":
                self.angle = ( -4.4, 0 )
                self.xpos = 228
                self.ypos = 352
            elif self.pos == "right":
                self.angle = ( 4.4, 0 )
                self.xpos = 406
                self.ypos = 352
    def move(self, yvel):
        self.ypos = self.ypos + yvel

class Panel(Enemy):
    def __init__(self, xpos, ypos, panel_type):
        Enemy.__init__(self,xpos,ypos)
        self.panel_type = panel_type
        self.health = 6
        self.active = True
        if self.panel_type == 0:
            self.image = pygame.image.load("gfx/Bubble_PanelA.png")
        elif self.panel_type == 1:
            self.image = pygame.image.load("gfx/Bubble_PanelB.png")
        elif self.panel_type == 2:
            self.image = pygame.image.load("gfx/Bubble_PanelC.png")
        elif self.panel_type == 3:
            self.image = pygame.image.load("gfx/Bubble_PanelD.png")

        if self.panel_type == 0:
            self.damageimage = pygame.image.load("gfx/Bubble_PanelA_Cracked.png")
        elif self.panel_type == 1:
            self.damageimage = pygame.image.load("gfx/Bubble_PanelB_Cracked.png")
        elif self.panel_type == 2:
            self.damageimage = pygame.image.load("gfx/Bubble_PanelC_Cracked.png")
        elif self.panel_type == 3:
            self.damageimage = pygame.image.load("gfx/Bubble_PanelD_Cracked.png")


        if self.panel_type == 0:
            self.deathimage = pygame.image.load("gfx/Panel_A_Death.png")
        elif self.panel_type == 1:
            self.deathimage = pygame.image.load("gfx/Panel_B_Death.png")
        elif self.panel_type == 2:
            self.deathimage = pygame.image.load("gfx/Panel_C_Death.png")
        elif self.panel_type == 3:
            self.deathimage = pygame.image.load("gfx/Panel_D_Death.png")
        else:
            print "Error"
        self.rect = self.image.get_rect()
        self.rect.x = self.xpos
        self.rect.y = self.ypos
        self.rect.width = PANEL_WIDTH
        if self.panel_type == 0:
            self.rect.height = PANEL_HEIGHT_A
        elif self.panel_type == 1:
            self.rect.height = PANEL_HEIGHT_B
        elif self.panel_type == 2:
            self.rect.height = PANEL_HEIGHT_C
        elif self.panel_type == 3:
            self.rect.height = PANEL_HEIGHT_D

        self.status = BubblesConstants.STATUS_ACTIVE

    def update(self, shots,player):
        if self.active == True :
            for shot in shots:
                if self.collision(shot):
                    if self.health < 6:
                        self.image = self.damageimage
                    self.health -= 1
                    shot.active = False        
                    if self.health <= 0:
                        self.image = self.deathimage
                        self.active = False
                        return BubblesConstants.DEAD_RETURN
            if self.collision(player):
                return BubblesConstants.COLLISION_PLAYER_RETURN
            return BubblesConstants.NO_COLLISION_RETURN

    def collision(self,shot):
        if (shot.rect.left > self.rect.left and shot.rect.right < self.rect.right) or (shot.rect.top > self.rect.top and shot.rect.bottom < self.rect.bottom):
            if shot.rect.colliderect(self.rect):
                return True
        else:
            # bottom left corner
            x = 0
            y = 0
            if shot.rect.left < self.rect.left and shot.rect.bottom > self.rect.bottom:
                x = self.rect.bottomleft[0]
                y = self.rect.bottomleft[1]
            # top left corner
            elif shot.rect.left < self.rect.left and shot.rect.top < self.rect.top:
                x = self.rect.topleft[0]
                y = self.rect.topleft[1]             
            # bottom right corner   
            elif shot.rect.right > self.rect.right and shot.rect.bottom > self.rect.bottom:
                x = self.rect.bottomright[0]
                y = self.rect.bottomright[1]
            # top right corner
            elif shot.rect.right > self.rect.right and shot.rect.top < self.rect.top:
                x = self.rect.topright[0]
                y = self.rect.topright[1]     
            else:
                return False
            distance = math.sqrt(math.pow(shot.xpos - x, 2) + math.pow(shot.ypos - y, 2))
            if distance < shot.radius:
                return True
        return False
    
    def draw(self,screen):
        screen.blit(self.image , self.rect)
        

    def move(self, yvel):
        self.rect.move_ip(0,yvel)
